#include "RenderSystem.h"
#include "../Resources/AssetManager.h"
#include "../ECS/Components/SpriteComponent.h"
#include "../ECS/Components/TransfomComponet.h"
#include "Rendering/Core/Camera2D.h"
#include "Rendering/Essentials/Shader.h"
#include "Log.h"

using namespace SCION_RENDERING;
using namespace SCION_RESOURCES;

namespace SCION_CORE::Systems
{
  RenderSystem::RenderSystem(ECS::Registry &registry)
      : m_Registry(registry), m_pBatchRenderer(nullptr)
  {
    m_pBatchRenderer = std::make_unique<SCION_RENDERING::BatchRenderer>();
  }
  void RenderSystem::Update()
  {

    auto &camera = m_Registry.GetContext<std::shared_ptr<SCION_RENDERING::Camera2D>>();
    if (!camera)
    {
      SCION_ERROR("Camera context is null!");
      return;
    }
    auto &assetManager = m_Registry.GetContext<std::shared_ptr<SCION_RESOURCES::AssetManager>>();

    auto &spriteShader = assetManager->GetShader("basic");
    auto cam_mat = camera->GetCameraMatrix();
    if (spriteShader.ShaderProgrameID() == 0)
    {
      SCION_ERROR("Shader program has not be created correctly!");
      return;
    }

    spriteShader.Enable();
    spriteShader.SetUniformMat4("uProjection", cam_mat);
    m_pBatchRenderer->Begin();

    auto view = m_Registry.GetRegistry().view<ECS::SpriteComponent, ECS::TransformComponent>();

    for (const auto &ent : view)
    {
      const auto &sprite = view.get<ECS::SpriteComponent>(ent);
      const auto &transform = view.get<ECS::TransformComponent>(ent);

      if (sprite.texture_name.empty())
      {
        continue;
      }

      const auto &texture = assetManager->GetTexture(sprite.texture_name);
      if (texture.GetID() == 0)
      {
        SCION_ERROR(fmt::format("Texture [{}] was not created correctly!", sprite.texture_name));
        continue;
      }

      glm::vec4 spriteRect{transform.position.x, transform.position.y, sprite.width, sprite.height};
      glm::vec4 uvRect{sprite.uvs.u, sprite.uvs.v, sprite.uvs.uv_width, sprite.uvs.uv_height};

      glm::mat4 model{1.f};
      if (transform.rotation > 0.f || transform.rotation < 0.f || transform.scale.x > 1.f || transform.scale.x < 1.f || transform.scale.y > 1.f || transform.scale.y < 1.f)
      {
        model = glm::translate(model, glm::vec3{transform.position, 0.f});
        model = glm::translate(model, glm::vec3{(sprite.width * transform.scale.x) * 0.5f, (sprite.height * transform.scale.y) * 0.5f, 0.f});
        model = glm::rotate(model, glm::radians(transform.rotation), glm::vec3{0.f, 0.f, 1.f});
        model = glm::translate(model, glm::vec3{(sprite.width * transform.scale.x) * -0.5f, (sprite.height * transform.scale.y) * -0.5f, 0.f});
        model = glm::scale(model, glm::vec3{transform.scale, 1.f});
        model = glm::translate(model, glm::vec3{-transform.position, 0.f});
      }

      // 假设 transform.position 是 glm::vec2
      // glm::mat4 model = glm::translate(
      //     glm::mat4{1.0f},
      //     glm::vec3{transform.position.x, transform.position.y, 0.0f});

      // if (transform.rotation != 0.0f || transform.scale != glm::vec2{1.0f, 1.0f})
      // {
      //   // 绕中心旋转/缩放
      //   model = glm::translate(model, glm::vec3{sprite.width * 0.5f, sprite.height * 0.5f, 0.0f});
      //   model = glm::rotate(model, glm::radians(transform.rotation), glm::vec3{0.0f, 0.0f, 1.0f});
      //   model = glm::scale(model, glm::vec3{transform.scale.x, transform.scale.y, 1.0f}); // 显式展开更安全
      //   model = glm::translate(model, glm::vec3{-sprite.width * 0.5f, -sprite.height * 0.5f, 0.0f});
      // }

      m_pBatchRenderer->AddSprite(spriteRect, uvRect, texture.GetID(), sprite.layer, model, sprite.color);
    }
    m_pBatchRenderer->End();
    m_pBatchRenderer->Render();

    spriteShader.Disable();
  }
}